`timescale 1ns / 1ps
`include "defines.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/06/10 21:20:17
// Design Name: 
// Module Name: ALU
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


// ALU: 实现多组算术运算和逻辑运算
module ALU (
    input [0:0] clk,
    input [0:0] rst,

    input  [`ALU_Operation_BUS] Operation,
    input  [`ALU_Parameter_BUS] A_Input,
    input  [`ALU_Parameter_BUS] B_Input,
    output reg[`ALU_Parameter_BUS] Result_Output,
    output reg[0:0] Carry_Output,
    output reg[0:0] Overflow_Output
);



    reg [63:0] Tmp;


    always @( *) begin
        Result_Output = 32'b0;
        Carry_Output = 1'b0;
        Overflow_Output = 1'b0;
        Tmp = 64'b0;
        case(Operation)
            `ALU_NOP: begin
                {Carry_Output,Result_Output} = 33'b0;
          end
            `ALU_ADD:begin
                {Carry_Output,Result_Output} = A_Input + B_Input;
                Overflow_Output = Result_Output[31] ^ Carry_Output;
            end
            `ALU_SUB:begin
                {Carry_Output,Result_Output} = A_Input - B_Input;
                Overflow_Output = Result_Output[31] ^ Carry_Output;
            end
            `ALU_XOR:begin
                Result_Output = A_Input ^ B_Input;
            end
            `ALU_OR:begin
                Result_Output = A_Input | B_Input;
            end
            `ALU_AND:begin
                Result_Output = A_Input & B_Input;
            end
            `ALU_Logical_Left_Shift:begin 
                Result_Output = A_Input << B_Input[4:0];
            end
            `ALU_Logical_Right_Shift:begin
                Result_Output = A_Input >> B_Input[4:0];
            end
            `ALU_Arithmetic_Right_Shift:begin
                if(A_Input[31]==1'b1)
                    Tmp = {32'b1,A_Input}>> B_Input[4:0];
                else if(A_Input[31]== 1'b0)
                    Tmp = {32'b0,A_Input}>> B_Input[4:0];
                Result_Output = Tmp[31:0];
            end


            `ALU_Compare_Less_Set_1:begin
                Tmp = A_Input - B_Input;
                Result_Output = (Tmp[31] == 1) ? 1'b1 : 1'b0;
            end
            `ALU_Unsign_Compare_Less_Set_1:begin
                {Carry_Output,Result_Output} = A_Input - B_Input;
                Result_Output = (Carry_Output == 1) ? 1'b1 : 1'b0;
            end
        endcase



    end









    always @(posedge clk) begin
        $display($time,"          ALU:  Results:%d,  Carry:%d,  Over:%d,",Result_Output,Carry_Output,Overflow_Output);
    end


endmodule
